/*
模板方法模式（Template Method Pattern）是一种行为型设计模式，它定义了一个算法的骨架，将一些步骤的实现延迟到子类中。
模板方法模式通过在父类中定义算法的骨架，将具体实现延迟到子类中，从而使得子类可以在不改变算法结构的情况下，重新定义算法的某些步骤。

模板方法模式由两部分组成：

1. 抽象父类（Abstract Class）：定义了算法的骨架，包含了一些抽象方法和具体方法。抽象方法用于延迟到子类中实现，具体方法用于实现算法的通用逻辑。
2. 具体子类（Concrete Class）：继承抽象父类，实现抽象方法，完成算法的具体实现。

使用模板方法模式的优点包括：

1. 提供了一种代码复用的方式，将公共代码放在抽象父类中，避免了代码的重复编写。
2. 提供了一种扩展的方式，子类可以通过实现抽象方法来改变算法的具体实现，而不需要修改父类的代码。
3. 提供了一种统一的算法骨架，可以确保算法的执行顺序和逻辑。

下面是一个使用模板方法模式的C语言例程，该例程模拟了一个制作咖啡的过程：
*/

#include <stdio.h>

// 抽象父类
typedef struct
{
    void (*brew)(void);
    void (*addCondiments)(void);
    void (*boilWater)(void);
    void (*pourInCup)(void);
    void (*prepareRecipe)(void);
} CaffeineBeverage;

// 具体子类1：制作咖啡
typedef struct
{
    CaffeineBeverage super;
} Coffee;

void brewCoffee()
{
    printf("Dripping coffee through filter\n");
}

void addCoffeeCondiments()
{
    printf("Adding sugar and milk\n");
}

void boilWater()
{
    printf("Boiling water\n");
}

void pourInCup()
{
    printf("Pouring coffee into cup\n");
}

void prepareCoffeeRecipe()
{
    CaffeineBeverage *beverage = (CaffeineBeverage *)malloc(sizeof(CaffeineBeverage));
    beverage->brew = brewCoffee;
    beverage->addCondiments = addCoffeeCondiments;
    beverage->boilWater = boilWater;
    beverage->pourInCup = pourInCup;

    beverage->boilWater();
    beverage->brew();
    beverage->pourInCup();
    beverage->addCondiments();

    free(beverage);
}

// 具体子类2：制作茶
typedef struct
{
    CaffeineBeverage super;
} Tea;

void steepTea()
{
    printf("Steeping the tea\n");
}

void addTeaCondiments()
{
    printf("Adding lemon\n");
}

void prepareTeaRecipe()
{
    CaffeineBeverage *beverage = (CaffeineBeverage *)malloc(sizeof(CaffeineBeverage));
    beverage->brew = steepTea;
    beverage->addCondiments = addTeaCondiments;
    beverage->boilWater = boilWater;
    beverage->pourInCup = pourInCup;

    beverage->boilWater();
    beverage->brew();
    beverage->pourInCup();
    beverage->addCondiments();

    free(beverage);
}

int main()
{
    printf("Making coffee:\n");
    prepareCoffeeRecipe();

    printf("\nMaking tea:\n");
    prepareTeaRecipe();

    return 0;
}

/*
在上面的例程中，首先定义了抽象父类CaffeineBeverage，其中包含了制作咖啡的算法骨架。
具体来说，brew方法用于冲泡咖啡，addCondiments方法用于添加调料，boilWater方法用于煮水，pourInCup方法用于倒入杯子。
在prepareRecipe方法中，按照算法骨架的顺序调用了这些方法。

然后，定义了具体子类Coffee和Tea，它们分别继承了抽象父类，并实现了抽象方法。
在具体子类中，重新定义了brew和addCondiments方法，以实现制作咖啡和茶的具体步骤。

在main函数中，创建了Coffee和Tea对象，并通过调用prepareRecipe方法来制作咖啡和茶。
这样，通过模板方法模式，我们可以定义一个算法的骨架，并将具体实现延迟到子类中，从而使得子类可以在不改变算法结构的情况下，重新定义算法的某些步骤。
*/